package com.topnav.mc.schedule.job;

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.js.lib.cache.SysCache;
import com.topnav.mc.admin.entity.Device;
import com.topnav.mc.admin.entity.DeviceChannel;
import com.topnav.mc.admin.entity.DeviceLog;
import com.topnav.mc.admin.entity.GbServer;
import com.topnav.mc.admin.entity.bean.DeviceBean;
import com.topnav.mc.admin.entity.bean.DeviceChannelBean;
import com.topnav.mc.admin.entity.bean.GbServerBean;
import com.topnav.mc.admin.entity.param.DeviceParam;
import com.topnav.mc.admin.entity.param.GbServerParam;
import com.topnav.mc.admin.service.IDeviceChannelService;
import com.topnav.mc.admin.service.IDeviceLogService;
import com.topnav.mc.admin.service.IDeviceService;
import com.topnav.mc.admin.service.IGbServerService;
import com.topnav.mc.gbserverapi.GbServerApi;
import com.topnav.mc.lock.SyncLock;
import com.topnav.mc.uitls.DeviceOnlineUtils;
import com.topnav.mc.uitls.MapUtil;
import com.topnav.mc.uitls.PlaceholderUtil;
import lombok.extern.slf4j.Slf4j;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.io.Serializable;
import java.util.*;
import static com.topnav.mc.common.Constant.*;


/**
 * 同步 国标设备及通道状态
 * 温度传感器数据上传
 * */
@Deprecated
@Component
@Slf4j
public class SyncGbDeviceOnlineJob implements Job, Serializable {
    @Autowired
    private IDeviceService deviceService;
    @Autowired
    private IGbServerService gbServerService;
    @Autowired
    private IDeviceChannelService deviceChannelService;
    @Autowired
    private IDeviceLogService deviceLogService;
    @Autowired
    private SysCache sysCache;
    @Resource
    private GbServerApi api;
    @Autowired
    private DeviceOnlineUtils deviceOnlineUtils;


    private String host = "http://%s:%s";
    private String url = null;
    List<DeviceChannelBean> channelList = new ArrayList<>();


    @Override
    @SyncLock(key = "SyncGbDeviceOnlineJob-LOCK", dueSec = 1 * 60 * 60)
    public void execute(JobExecutionContext context) throws JobExecutionException {
        try {
            ;
            this.execute1();
        } catch (JobExecutionException e) {
            throw e;
        } catch (Exception e) {
            log.error("******* SyncGbDeviceOnlineJob.execute: {}", e.toString());
        }
    }

    /**
     * 已不用
     * @throws Exception
     */
    @Deprecated
    public void execute1() throws Exception {
        return;
    }

    //@SyncLock(key = "SyncGbDeviceOnlineJob-LOCK", dueSec = 1 * 60 * 60)
    public void execute2() throws Exception {
        log.debug(">>>>>> 正在同步设备及状态 ......");
        return;

/*        String serverHost = null;
        String url = null;
        String result = null;
        boolean found = false;
        int remoteOnline = 0;// 远程设备在线
        List<Device> remoteDevices = new ArrayList<>();
        List<DeviceBean> localDevices = new ArrayList<>();

        //所有在线的国标服务端
        QueryWrapper<GbServerParam> gbWrapper = new QueryWrapper<>();
        gbWrapper.eq("online", 1);
        List<GbServerBean> gbServerList = gbServerService.listInfo(gbWrapper);
        for (GbServerBean gbServerBean : gbServerList) {
            url = String.format(host, gbServerBean.getHost(), gbServerBean.getApiPort());
            localDevices = this.getLocalDevices(gbServerBean);
            remoteDevices = this.getRemoteDevices(gbServerBean, localDevices);

            //处理远程未注册的调备状态为离线
            this.remoteUnRegDevice(localDevices);

            *//** 对于在线设备同步通道信息 *//*
            channelList.clear();
            for (Device gbDevice : remoteDevices) {
                //在线设备才同步 通道
                if (gbDevice.getOnline()) {
                    //查询此设备下所有的通道
                    result = api.syncChannels(url, gbDevice.getCode());
                    JSONObject json = JSONObject.parseObject(result);
                    if ("0".equals(json.get("code").toString())) {
                        //取得同步结束
                        this.syncDeviceStatus(url, gbDevice);
                    }
                }
                Thread.sleep(20L);
            }

            this.updateChannelToDb();
            this.updateDeviceLog(localDevices,remoteDevices);
        }*/
    }


    /**
     * 汇聚远程的通道 更新到 channelList 结果集
     *
     * @param device
     */
    private void CollectChannel(Device device) {
        /** 更新设备的通道状态 */
        Integer pageSize = 50;
        Integer pageNum = 0;
        Integer total = pageSize + 1;
        String result = null;
        while (total > pageNum * pageSize) {
            pageNum++;
            try {
                result = api.channels(url, device.getCode(), pageNum.toString(), pageSize.toString());
                JSONObject json = JSONObject.parseObject(result);
                if ("0".equals(json.get("code").toString())) {
                    JSONObject data = (JSONObject) json.get("data");
                    if (data != null) {
                        total = (Integer) data.get("total");
                        List<JSONObject> list = (List<JSONObject>) data.get("list");
                        for (JSONObject jsonObject : list) {
                            DeviceChannelBean bbChannelBean = new DeviceChannelBean();
                            bbChannelBean.setDeviceCode(jsonObject.get("deviceId").toString());
                            bbChannelBean.setChannelCode(jsonObject.get("channelId").toString());
                            //如果是在线的执法则强制通道为在线
                            if (!device.getOnline()){
                                //设备不线，通道也不能在线
                                bbChannelBean.setStatus(0);
                            }else {
                                //执法仪
                                bbChannelBean.setStatus(
                                    device.getType() == 2 && device.getOnline()?1:Integer.valueOf(jsonObject.get("status").toString())
                                );
                            }
                            //type 2执法仪，3摄像头
                            bbChannelBean.setType(device.getType());
                            channelList.add(bbChannelBean);
                        }
                    }
                } else {
                    log.error("****** code:{} msg:{}", json.get("code"), json.get("msg"));
                }
                Thread.sleep(100L);
            } catch (Exception e) {
                log.error("******* {}", e.toString());
            }
        }
    }

    /**
     * 更新通道到数据库
     */
    private void updateChannelToDb(){
        boolean found=false;
        boolean isAlarmChn = false;

        /** 更新通道状态到数据库 */
        UpdateWrapper<DeviceChannel> gbChannelUpdateWrapper = new UpdateWrapper<>();
        List<DeviceChannelBean> localChannels = deviceChannelService.listInfo();

        for(DeviceChannelBean remoteChannel:channelList){
            found=false;isAlarmChn=false;
            for(DeviceChannelBean localChannel:localChannels){
                try{
                    gbChannelUpdateWrapper.clear();
                    if (remoteChannel.getDeviceCode().equals(localChannel.getDeviceCode())
                            && remoteChannel.getChannelCode().equals(localChannel.getChannelCode())
                    ){
                        if (remoteChannel.getType() == 3)
                            gbChannelUpdateWrapper.set("status",remoteChannel.getStatus());
                        else
                            gbChannelUpdateWrapper.set("status",1);

                        gbChannelUpdateWrapper.eq("device_id",localChannel.getDeviceId());
                        gbChannelUpdateWrapper.eq("channel_code",localChannel.getChannelCode());
                        deviceChannelService.update(gbChannelUpdateWrapper);
                        found=true;
                        break;
                    }
                }catch (Exception e){
                    log.error("******* {}",e.toString());
                }
            }

            /** 如果本没有注册通道则新通道*/
            if (!found){
                //报警通道
                isAlarmChn = remoteChannel.getChannelCode().length() >= 13 && remoteChannel.getChannelCode().indexOf("134")==9?true:false;
                QueryWrapper<Device> wrapper1 = new QueryWrapper<>();
                wrapper1.eq("code",remoteChannel.getDeviceId());
                Device device = deviceService.getOne(wrapper1,false);
                if (device != null){
                    if (device.getType() == 2) {
                        //执法仪
                        UpdateWrapper<Device> updateWrapper = new UpdateWrapper<>();
                        updateWrapper.eq("id",device.getId());
                        if (isAlarmChn){
                            updateWrapper.set("default_alarm_channel",remoteChannel.getChannelCode());
                        }else{
                            updateWrapper.set("default_channel",remoteChannel.getChannelCode());
                        }
                        deviceService.update(updateWrapper);
                    }
                    DeviceChannel deviceChannel = new DeviceChannel();
                    deviceChannel.setDeviceId(device.getId());
                    deviceChannel.setDeviceCode(device.getCode());
                    deviceChannel.setChannelCode(remoteChannel.getChannelCode());
                    deviceChannel.setName(remoteChannel.getName());
                    deviceChannel.setStatus(device.getType() == 2?1:remoteChannel.getStatus());
                    deviceChannel.setCreateTime(new Date());
                    deviceChannel.setUpdateTime(new Date());
                    deviceChannel.setHasAudio(false);
                    deviceChannelService.save(deviceChannel);
                }
            }

        }
    }





    /**
     * 递归查询同步状态
     * @return
     */
    private boolean syncDeviceStatus(String url,Device device){
        try{
            String result = api.syncStatus(url,device.getCode());
            JSONObject json1 = JSONObject.parseObject(result);
            if ("0".equals(json1.get("code").toString())){
                JSONObject data = (JSONObject)json1.get("data");
                if (data != null){
                    // 正在同步未完成，1秒以后再查，直到结束
                    if (Integer.valueOf(data.get("current").toString()) < Integer.valueOf(data.get("total").toString())){
                        log.info("******* 正在同步 {}条, 总{}条",json1.get("current"),json1.get("total"));
                        Thread.sleep(500l);
                        return syncDeviceStatus(url,device);
                    }else {
                        this.CollectChannel(device);
                    }
                }
                return true;
            }else{
                log.error("******* {}",json1.get("msg"));
                return true;
            }

        }catch (Exception e){
            log.error("****** {}",e.toString());
            return true;
        }
    }
    /**
     * 远程未注册的设备置为离线状态
     * @param localDevices
     */
    private void remoteUnRegDevice(List<DeviceBean> localDevices){
        for(DeviceBean deviceBean : localDevices){
            if (!deviceBean.isTempFlag()){
                if (deviceBean.getOnline() == true){
                    //this.updateDeviceLog(deviceBean,false);
                    UpdateWrapper<Device> uDevwrapper = new UpdateWrapper<>();
                    uDevwrapper.set("online",false);
                    uDevwrapper.eq("id",deviceBean.getId());
                    deviceService.update(uDevwrapper);
                    deviceOnlineUtils.setOffline(deviceBean.getCode());

                    UpdateWrapper<DeviceChannel> uChnwrapper = new UpdateWrapper<>();
                    uChnwrapper.set("status",0);
                    uChnwrapper.eq("device_id",deviceBean.getId());
                    deviceChannelService.update(uChnwrapper);

                }
            }
        }
    }

    /**
     * 查询本地的devices
     * @param gbServerBean
     * @return 本地设备列表
     */
    private List<DeviceBean> getLocalDevices(GbServerBean gbServerBean){
        LambdaQueryWrapper<DeviceParam> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Device::getGbServerId,gbServerBean.getId());
        return deviceService.listInfo(wrapper);
    }

    /**
     * 查询远程devices,本地未注册的排除
     * @param gbServerBean
     * @param localGbDevices
     * @return 远程设备列表
     */
    private List<Device> getRemoteDevices(GbServerBean gbServerBean,List<DeviceBean> localGbDevices){
        //远程设备
        String result=null;
        Integer pageSize=50;
        Integer pageNum=0;
        Integer total = pageSize + 1;
        List<Device> devices = new ArrayList<>();
        while(total > pageNum * pageSize){
            try{
                /** 分页查询 远端所有的设备 */
                pageNum++;
                url = String.format(host,gbServerBean.getHost(),gbServerBean.getApiPort());
                result = api.devices(url,pageNum.toString(),pageSize.toString());

                JSONObject json = JSONObject.parseObject(result);
                Boolean online = false;
                if ("0".equals(json.get("code").toString())){
                    JSONObject data = (JSONObject)json.get("data");
                    if (data != null){
                        total = (Integer)data.get("total");
                        List<JSONObject> list = ( List<JSONObject>)data.get("list");
                        for(JSONObject jsonObject : list){
                            //更新本地设备在线状态
                            for(DeviceBean deviceBean : localGbDevices){
                                if (deviceBean.getCode().equals(jsonObject.get("deviceId"))){
                                    Device gbDevice1 = new Device();
                                    gbDevice1.setId(deviceBean.getId());
                                    gbDevice1.setCode(jsonObject.get("deviceId").toString());
                                    gbDevice1.setType(deviceBean.getType());
                                    if ("1".equals(jsonObject.get("online").toString())){
                                        gbDevice1.setOnline(true);
                                    }else{
                                        gbDevice1.setOnline(false);
                                    }
                                    //远端和本地设备编号一致的加入remoteDevices列表
                                    devices.add(gbDevice1);

                                    //远程已注册此设备
                                    deviceBean.setTempFlag(true);
                                    break;
                                }
                            }
                        }
                    }else{
                        log.error("****** code:{} msg:{}",json.get("code"),json.get("msg"));
                    }
                }
                Thread.sleep(100L);
            }catch (Exception e ){
                log.error("******* {}",e.toString());
            }
        }
        return devices;
    }

    /**
     * 上下线日志登记
     * @param localDevice
     * @param remoteDevices
     */
    private void updateDeviceLog(List<DeviceBean> localDevice,List<Device> remoteDevices){
        //在线时间，状态写表数据库
        Integer lOnline = null;
        Integer rOnline = null;
        Integer action = 0;
        for(DeviceBean ldevice:localDevice){
            rOnline=0;
            lOnline = ldevice.getOnline()?1:0;

            for(Device rDevice : remoteDevices){
                if (ldevice.getCode().equals(rDevice.getCode())){
                    rOnline = rDevice.getOnline()?1:0;
                }
            }
            if (lOnline != rOnline){
                action = lOnline == 0 && rOnline == 1?1:0;

                UpdateWrapper<Device> uDevwrapper = new UpdateWrapper<>();
                uDevwrapper.set("online",false);
                uDevwrapper.eq("id",ldevice.getId());
                deviceService.update(uDevwrapper);
                deviceOnlineUtils.setOffline(ldevice.getCode());

                DeviceLog deviceLog = new DeviceLog();
                deviceLog.setDeviceId(ldevice.getId());
                deviceLog.setDeviceCode(ldevice.getCode());
                deviceLog.setAction(action);
                String location = (String) sysCache.hget(DEVICE_CURRENT_LOCATION, ldevice.getCode());
                if (location != null) {
                    JSONObject json = JSONObject.parseObject(location);
                    deviceLog.setLongitude(json.get("longitude").toString());
                    deviceLog.setLatitude(json.get("latitude").toString());
                } else {
                    deviceLog.setLongitude(MapUtil.getCenterPoint().get("longitude").toString());
                    deviceLog.setLatitude(MapUtil.getCenterPoint().get("latitude").toString());
                }
                deviceLog.setCreateTime(new Date());
                deviceLogService.save(deviceLog);

                //更新设备状态
                UpdateWrapper<Device> updateWrapper = new UpdateWrapper<>();
                updateWrapper.set("online",rOnline==1?true:false);
                updateWrapper.eq("id",ldevice.getId());
                deviceService.update(updateWrapper);
            }

            if (rOnline == 1){
                deviceOnlineUtils.setOnline(ldevice.getCode());
            }else{
                deviceOnlineUtils.setOffline(ldevice.getCode());
            }
        }
    }

}
